From 3454fab5993de527ef15688161fa0a43e83a1561 Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Fri, 13 Aug 2004 14:17:22 +0000 Subject: [PATCH] bitkeeper revision 1.1159.1.53 (411ccd729CC_RzyLGa4nViY2XcSdig) Separate controller backend from the controller factory, allowing each controller to have its own backend domain. --- tools/python/xen/xend/server/blkif.py | 215 +++++++++++---------- tools/python/xen/xend/server/controller.py | 109 ++++++++++- tools/python/xen/xend/server/netif.py | 86 +++++---- 3 files changed, 268 insertions(+), 142 deletions(-) diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py index cc49688ef5..bea848bfcf 100755 --- a/tools/python/xen/xend/server/blkif.py +++ b/tools/python/xen/xend/server/blkif.py @@ -13,20 +13,109 @@ import channel import controller from messages import * -class BlkifControllerFactory(controller.ControllerFactory): - """Factory for creating block device interface controllers. - Also handles the 'back-end' channel to the device driver domain. +class BlkifBackendController(controller.BackendController): + """ Handler for the 'back-end' channel to a device driver domain. """ - def __init__(self): - controller.ControllerFactory.__init__(self) + def __init__(self, factory, dom): + controller.BackendController.__init__(self, factory, dom) self.addMethod(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED, self.recv_be_driver_status_changed) self.attached = 1 self.registerChannel() + + def respond_be_create(self, msg, d): + """Response handler for a be_create message. + Calls I{d} with the block interface created. + + @param msg: message + @type msg: xu message + @param d: deferred to call + @type d: Deferred + """ + val = unpackMsg('blkif_be_create_t', msg) + blkif = self.factory.getInstanceByDom(val['domid']) + d.callback(blkif) + + def respond_be_connect(self, msg): + """Response handler for a be_connect message. + + @param msg: message + @type msg: xu message + """ + val = unpackMsg('blkif_be_connect_t', msg) + blkif = self.factory.getInstanceByDom(val['domid']) + if blkif: + blkif.send_fe_interface_status_changed() + else: + pass + + def respond_be_vbd_create(self, msg, dev, d): + """Response handler for a be_vbd_create message. + Tries to grow the vbd, and passes the deferred I{d} on for + the grow to call. + + @param msg: message + @type msg: xu message + @param dev: device + @type dev: BlkDev + @param d: deferred to call + @type d: Deferred + """ + val = unpackMsg('blkif_be_vbd_create_t', msg) + blkif = self.factory.getInstanceByDom(val['domid']) + if blkif: + d1 = defer.Deferred() + d1.addCallback(self.respond_be_vbd_grow, dev, d) + if d: d1.addErrback(d.errback) + blkif.send_be_vbd_grow(val['vdevice'], response=d1) + else: + pass + + def respond_be_vbd_grow(self, msg, dev, d): + """Response handler for a be_vbd_grow message. + + @param msg: message + @type msg: xu message + @param dev: device + @type dev: BlkDev + @param d: deferred to call + @type d: Deferred or None + """ + val = unpackMsg('blkif_be_vbd_grow_t', msg) + status = val['status'] + if status != BLKIF_BE_STATUS_OKAY: + raise XendError("Adding extent to vbd failed: device %x, error %d" + % (val['extent.device'], status)) + if d: + d.callback(dev) + + def recv_be_driver_status_changed(self, msg, req): + """Request handler for be_driver_status_changed messages. + + @param msg: message + @type msg: xu message + @param req: request flag (true if the msg is a request) + @type req: bool + """ + val = unpackMsg('blkif_be_driver_status_changed_t', msg) + status = val['status'] + if status == BLKIF_DRIVER_STATUS_UP and not self.attached: + for blkif in self.factory.getInstances(): + if blkif.backendController == self: + blkif.detach() + + +class BlkifControllerFactory(controller.SplitControllerFactory): + """Factory for creating block device interface controllers. + """ - def createInstance(self, dom, recreate=0): + def __init__(self): + controller.SplitControllerFactory.__init__(self) + self.attached = 1 + + def createInstance(self, dom, recreate=0, backend=0): """Create a block device controller for a domain. @param dom: domain @@ -41,13 +130,13 @@ class BlkifControllerFactory(controller.ControllerFactory): if blkif: d.callback(blkif) else: - blkif = BlkifController(self, dom) + blkif = BlkifController(self, dom, backend) self.addInstance(blkif) if recreate: d.callback(blkif) else: d1 = defer.Deferred() - d1.addCallback(self.respond_be_create, d) + d1.addCallback(blkif.backendController.respond_be_create, d) d1.addErrback(d.errback) blkif.send_be_create(response=d1) return d @@ -76,6 +165,9 @@ class BlkifControllerFactory(controller.ControllerFactory): blkif = self.getInstanceByDom(dom) return (blkif and blkif.getDevice(vdev)) or None + def createBackendController(self, dom): + return BlkifBackendController(self, dom) + def setControlDomain(self, dom, recreate=0): """Set the back-end block device controller domain. @@ -134,88 +226,7 @@ class BlkifControllerFactory(controller.ControllerFactory): for blkif in self.getInstances(): blkif.reattached() - def respond_be_create(self, msg, d): - """Response handler for a be_create message. - Calls I{d} with the block interface created. - - @param msg: message - @type msg: xu message - @param d: deferred to call - @type d: Deferred - """ - val = unpackMsg('blkif_be_create_t', msg) - blkif = self.getInstanceByDom(val['domid']) - d.callback(blkif) - - def respond_be_connect(self, msg): - """Response handler for a be_connect message. - @param msg: message - @type msg: xu message - """ - val = unpackMsg('blkif_be_connect_t', msg) - blkif = self.getInstanceByDom(val['domid']) - if blkif: - blkif.send_fe_interface_status_changed() - else: - pass - - def respond_be_vbd_create(self, msg, dev, d): - """Response handler for a be_vbd_create message. - Tries to grow the vbd, and passes the deferred I{d} on for - the grow to call. - - @param msg: message - @type msg: xu message - @param dev: device - @type dev: BlkDev - @param d: deferred to call - @type d: Deferred - """ - val = unpackMsg('blkif_be_vbd_create_t', msg) - blkif = self.getInstanceByDom(val['domid']) - if blkif: - d1 = defer.Deferred() - d1.addCallback(self.respond_be_vbd_grow, dev, d) - if d: d1.addErrback(d.errback) - blkif.send_be_vbd_grow(val['vdevice'], response=d1) - else: - pass - - def respond_be_vbd_grow(self, msg, dev, d): - """Response handler for a be_vbd_grow message. - - @param msg: message - @type msg: xu message - @param dev: device - @type dev: BlkDev - @param d: deferred to call - @type d: Deferred or None - """ - val = unpackMsg('blkif_be_vbd_grow_t', msg) - status = val['status'] - if status != BLKIF_BE_STATUS_OKAY: - raise XendError("Adding extent to vbd failed: device %x, error %d" - % (val['extent.device'], status)) - if self.attached: - if d: - d.callback(dev) - else: - self.reattachDevice(val['domid'], val['vdevice']) - - def recv_be_driver_status_changed(self, msg, req): - """Request handler for be_driver_status_changed messages. - - @param msg: message - @type msg: xu message - @param req: request flag (true if the msg is a request) - @type req: bool - """ - val = unpackMsg('blkif_be_driver_status_changed_t', msg) - status = val['status'] - if status == BLKIF_DRIVER_STATUS_UP and not self.attached: - for blkif in self.getInstances(): - blkif.detach() class BlkDev(controller.Dev): """Info record for a block device. @@ -251,13 +262,13 @@ class BlkDev(controller.Dev): log.debug("Destroying vbd domain=%d vdev=%d", self.controller.dom, self.vdev) self.controller.send_be_vbd_destroy(self.vdev) -class BlkifController(controller.Controller): +class BlkifController(controller.SplitController): """Block device interface controller. Handles all block devices for a domain. """ - def __init__(self, factory, dom): - controller.Controller.__init__(self, factory, dom) + def __init__(self, factory, dom, backend): + controller.SplitController.__init__(self, factory, dom, backend) self.devices = {} self.addMethod(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED, @@ -322,7 +333,7 @@ class BlkifController(controller.Controller): d.callback(dev) else: d1 = defer.Deferred() - d1.addCallback(self.factory.respond_be_vbd_create, dev, d) + d1.addCallback(self.backendController.respond_be_vbd_create, dev, d) d1.addErrback(d.errback) self.send_be_vbd_create(vdev, response=d1) return d @@ -346,7 +357,7 @@ class BlkifController(controller.Controller): for dev in self.devices.values(): dev.attached = 0 d1 = defer.Deferred() - d1.addCallback(self.factory.respond_be_vbd_create, None, None) + d1.addCallback(self.backendController.respond_be_vbd_create, None, None) self.send_be_vbd_create(vdev, response=d1) def reattachDevice(self, vdev): @@ -389,8 +400,8 @@ class BlkifController(controller.Controller): 'evtchn' : self.evtchn['port1'], 'shmem_frame' : val['shmem_frame'] }) d = defer.Deferred() - d.addCallback(self.factory.respond_be_connect) - self.factory.writeRequest(msg, response=d) + d.addCallback(self.backendController.respond_be_connect) + self.backendController.writeRequest(msg, response=d) def send_fe_interface_status_changed(self, response=None): msg = packMsg('blkif_fe_interface_status_changed_t', @@ -403,21 +414,21 @@ class BlkifController(controller.Controller): msg = packMsg('blkif_be_create_t', { 'domid' : self.dom, 'blkif_handle' : 0 }) - self.factory.writeRequest(msg, response=response) + self.backendController.writeRequest(msg, response=response) def send_be_disconnect(self, response=None): log.debug('>BlkifController>send_be_disconnect> dom=%d', self.dom) msg = packMsg('blkif_be_disconnect_t', { 'domid' : self.dom, 'blkif_handle' : 0 }) - self.factory.writeRequest(msg, response=response) + self.backendController.writeRequest(msg, response=response) def send_be_destroy(self, response=None): log.debug('>BlkifController>send_be_destroy> dom=%d', self.dom) msg = packMsg('blkif_be_destroy_t', { 'domid' : self.dom, 'blkif_handle' : 0 }) - self.factory.writeRequest(msg, response=response) + self.backendController.writeRequest(msg, response=response) def send_be_vbd_create(self, vdev, response=None): dev = self.devices[vdev] @@ -426,7 +437,7 @@ class BlkifController(controller.Controller): 'blkif_handle' : 0, 'vdevice' : dev.vdev, 'readonly' : dev.readonly() }) - self.factory.writeRequest(msg, response=response) + self.backendController.writeRequest(msg, response=response) def send_be_vbd_grow(self, vdev, response=None): dev = self.devices[vdev] @@ -437,7 +448,7 @@ class BlkifController(controller.Controller): 'extent.device' : dev.device, 'extent.sector_start' : dev.start_sector, 'extent.sector_length' : dev.nr_sectors }) - self.factory.writeRequest(msg, response=response) + self.backendController.writeRequest(msg, response=response) def send_be_vbd_destroy(self, vdev, response=None): log.debug('>BlkifController>send_be_vbd_destroy> dom=%d vdev=%d', self.dom, vdev) @@ -447,5 +458,5 @@ class BlkifController(controller.Controller): 'blkif_handle' : 0, 'vdevice' : dev.vdev }) del self.devices[vdev] - self.factory.writeRequest(msg, response=response) + self.backendController.writeRequest(msg, response=response) diff --git a/tools/python/xen/xend/server/controller.py b/tools/python/xen/xend/server/controller.py index b3795aeced..cea9c38dfb 100755 --- a/tools/python/xen/xend/server/controller.py +++ b/tools/python/xen/xend/server/controller.py @@ -270,7 +270,7 @@ class CtrlMsgRcvr: else: print 'CtrlMsgRcvr>writeResponse>', 'no channel!', self -class ControllerFactory(CtrlMsgRcvr): +class ControllerFactory: """Abstract class for factories creating controllers for a domain. Maintains a table of instances. @@ -281,8 +281,8 @@ class ControllerFactory(CtrlMsgRcvr): """ def __init__(self): - CtrlMsgRcvr.__init__(self) self.instances = {} + self.backends = {} self.dom = 0 def addInstance(self, instance): @@ -370,6 +370,111 @@ class Controller(CtrlMsgRcvr): self.deregisterChannel() self.factory.instanceClosed(self) +class SplitControllerFactory(ControllerFactory): + """Factory for SplitControllers. + + @ivar backends: mapping of domain id to backend + @type backends: {int: BackendController} + """ + + def __init__(self): + ControllerFactory.__init__(self) + self.backends = {} + + def createInstance(self, dom, recreate=0, backend=0): + """Create an instance. Define in a subclass. + + @param dom: domain + @type dom: int + @param recreate: true if the instance is being recreated (after xend restart) + @type recreate: int + @param backend: backend domain + @type backend: int + @return: controller instance + @rtype: SplitController (or subclass) + """ + raise NotImplementedError() + + def getBackendController(self, dom): + """Get the backend controller for a domain. + + @param dom: domain + @return: backend controller + """ + ctrlr = self.backends.get(dom) + if ctrlr is None: + ctrlr = self.createBackendController(dom) + self.backends[dom] = ctrlr + return ctrlr + + def createBackendController(self, dom): + """Create a backend controller. Define in a subclass. + + @param dom: domain + """ + raise NotImplementedError() + + def delBackendController(self, ctrlr): + """Remove a backend controller. + + @param ctrlr: backend controller + """ + if ctrlr.dom in self.backends: + del self.backends[ctrlr.dom] + + def backendControllerClosed(self, ctrlr): + """Callback called when a backend is closed. + """ + self.delBackendController(ctrlr) + +class BackendController(CtrlMsgRcvr): + """Abstract class for a backend device controller attached to a domain. + + @ivar factory: controller factory + @type factory: ControllerFactory + @ivar dom: domain + @type dom: int + @ivar channel: channel to the domain + @type channel: Channel + """ + + + def __init__(self, factory, dom): + CtrlMsgRcvr.__init__(self) + self.factory = factory + self.dom = int(dom) + self.channel = None + + def close(self): + self.lostChannel() + + def lostChannel(self): + self.deregisterChannel() + self.factory.instanceClosed(self) + + +class SplitController(Controller): + """Abstract class for a device controller attached to a domain. + A SplitController has a BackendContoller. + """ + + def __init__(self, factory, dom, backend): + Controller.__init__(self, factory, dom) + self.backendDomain = None + self.backendController = None + self.setBackendDomain(backend) + + def setBackendDomain(self, dom): + ctrlr = self.factory.getBackendController(dom) + self.backendDomain = ctrlr.dom + self.backendController = ctrlr + + def getBackendDomain(self): + return self.backendDomain + + def getBackendController(self): + return self.backendController + class Dev: """Abstract class for a device attached to a device controller. diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py index 7a33ab8489..f4247c670f 100755 --- a/tools/python/xen/xend/server/netif.py +++ b/tools/python/xen/xend/server/netif.py @@ -18,20 +18,49 @@ import channel import controller from messages import * -class NetifControllerFactory(controller.ControllerFactory): - """Factory for creating network interface controllers. - Also handles the 'back-end' channel to the device driver domain. +class NetifBackendController(controller.BackendController): + """Handler for the 'back-end' channel to a device driver domain. """ - - def __init__(self): - controller.ControllerFactory.__init__(self) + + def __init__(self, factory, dom): + controller.BackendController.__init__(self, factory, dom) self.addMethod(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED, self.recv_be_driver_status_changed) self.attached = 1 self.registerChannel() - def createInstance(self, dom, recreate=0): + def respond_be_connect(self, msg): + val = unpackMsg('netif_be_connect_t', msg) + dom = val['domid'] + vif = val['netif_handle'] + netif = self.factory.getInstanceByDom(dom) + if netif: + netif.send_interface_connected(vif) + else: + log.warning("respond_be_connect> unknown vif dom=%d vif=%d", dom, vif) + pass + + def recv_be_driver_status_changed(self, msg, req): + val = unpackMsg('netif_be_driver_status_changed_t', msg) + status = val['status'] + if status == NETIF_DRIVER_STATUS_UP and not self.attached: + # If we are not attached the driver domain was changed, and + # this signals the new driver domain is ready. + for netif in self.factory.getInstances(): + if netif.backendController == self: + netif.reattach_devices() + self.attached = 1 + +class NetifControllerFactory(controller.SplitControllerFactory): + """Factory for creating network interface controllers. + """ + + def __init__(self): + controller.ControllerFactory.__init__(self) + self.attached = 1 + + def createInstance(self, dom, recreate=0, backend=0): """Create or find the network interface controller for a domain. @param dom: domain @@ -40,7 +69,7 @@ class NetifControllerFactory(controller.ControllerFactory): """ netif = self.getInstanceByDom(dom) if netif is None: - netif = NetifController(self, dom) + netif = NetifController(self, dom, backend=backend) self.addInstance(netif) return netif @@ -63,6 +92,9 @@ class NetifControllerFactory(controller.ControllerFactory): netif = self.getInstanceByDom(dom) return (netif and netif.getDevice(vif)) or None + def createBackendController(self, dom): + return NetifBackendController(self, dom) + def setControlDomain(self, dom, recreate=0): """Set the 'back-end' device driver domain. @@ -83,27 +115,6 @@ class NetifControllerFactory(controller.ControllerFactory): """ return self.dom - def respond_be_connect(self, msg): - val = unpackMsg('netif_be_connect_t', msg) - dom = val['domid'] - vif = val['netif_handle'] - netif = self.getInstanceByDom(dom) - if netif: - netif.send_interface_connected(vif) - else: - log.warning("respond_be_connect> unknown vif dom=%d vif=%d", dom, vif) - pass - - def recv_be_driver_status_changed(self, msg, req): - val = unpackMsg('netif_be_driver_status_changed_t', msg) - status = val['status'] - if status == NETIF_DRIVER_STATUS_UP and not self.attached: - # If we are not attached the driver domain was changed, and - # this signals the new driver domain is ready. - for netif in self.getInstances(): - netif.reattach_devices() - self.attached = 1 - class NetDev(controller.Dev): """Info record for a network device. """ @@ -207,14 +218,13 @@ class NetDev(controller.Dev): self.controller.send_be_disconnect(self.vif, response=d) -class NetifController(controller.Controller): +class NetifController(controller.SplitController): """Network interface controller. Handles all network devices for a domain. """ - def __init__(self, factory, dom): - controller.Controller.__init__(self, factory, dom) + def __init__(self, factory, dom, backend): + controller.SplitController.__init__(self, factory, dom, backend) self.devices = {} - self.addMethod(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED, self.recv_fe_driver_status_changed) @@ -317,8 +327,8 @@ class NetifController(controller.Controller): 'tx_shmem_frame' : val['tx_shmem_frame'], 'rx_shmem_frame' : val['rx_shmem_frame'] }) d = defer.Deferred() - d.addCallback(self.factory.respond_be_connect) - self.factory.writeRequest(msg, response=d) + d.addCallback(self.backendController.respond_be_connect) + self.backendController.writeRequest(msg, response=d) def send_interface_connected(self, vif, response=None): dev = self.devices[vif] @@ -335,14 +345,14 @@ class NetifController(controller.Controller): { 'domid' : self.dom, 'netif_handle' : dev.vif, 'mac' : dev.mac }) - self.factory.writeRequest(msg, response=response) + self.backendController.writeRequest(msg, response=response) def send_be_disconnect(self, vif, response=None): dev = self.devices[vif] msg = packMsg('netif_be_disconnect_t', { 'domid' : self.dom, 'netif_handle' : dev.vif }) - self.factory.writeRequest(msg, response=response) + self.backendController.writeRequest(msg, response=response) def send_be_destroy(self, vif, response=None): dev = self.devices[vif] @@ -350,4 +360,4 @@ class NetifController(controller.Controller): msg = packMsg('netif_be_destroy_t', { 'domid' : self.dom, 'netif_handle' : vif }) - self.factory.writeRequest(msg, response=response) + self.backendController.writeRequest(msg, response=response) -- 2.30.2